package org.example.juc;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 自定义队列锁
 */
public class CLHLock implements Lock {

    ThreadLocal<Node> local = new ThreadLocal<>();

    // 队列尾指针
    AtomicReference<Node> tail = new AtomicReference<>(null);

    public CLHLock() {
        // 设置空节点
        tail.set(new Node(false, null));
    }

    @Override
    public void lock() {
        // 当前线程抢锁
        Node node = new Node(true, null);
        Node preNode = tail.get();
        // CAS自旋，将当前节点加入tail
        // 如果加入失败，就一直自旋
        while (!tail.compareAndSet(preNode, node)) {
            preNode = tail.get();
        }

        // 监听上一个节点是否释放锁
        node.setPreNode(preNode);
        while (preNode.isLocked()) {
            // 出让CPU
            Thread.yield();
        }

        local.set(node);
    }

    @Override
    public void unlock() {
        Node node = local.get();
        node.setLocked(false);
        node.setPreNode(null);
        local.set(null);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        throw new IllegalStateException("方法'lockInterruptibly'尚未实现");
    }

    @Override
    public boolean tryLock() {
        throw new IllegalStateException("方法'tryLock'尚未实现");
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        throw new IllegalStateException("方法'tryLock'尚未实现");
    }

    @Override
    public Condition newCondition() {
        throw new IllegalStateException("方法'newCondition'尚未实现");
    }

    class Node {
        private volatile boolean locked = false;

        private Node preNode;

        public Node(boolean locked, Node node) {
            this.locked = locked;
            this.preNode = node;
        }

        public boolean isLocked() {
            return locked;
        }

        public void setLocked(boolean locked) {
            this.locked = locked;
        }

        public Node getPreNode() {
            return preNode;
        }

        public void setPreNode(Node preNode) {
            this.preNode = preNode;
        }
    }

    public static void main(String[] args) throws Exception {
        CLHLock lock = new CLHLock();
        VolatileTest test = new VolatileTest();
        int MAX_THREAD = 10;
        ExecutorService service = Executors.newFixedThreadPool(MAX_THREAD);
        CountDownLatch latch = new CountDownLatch(MAX_THREAD);

        for (int i = 0; i < MAX_THREAD; i++) {
            service.submit(() -> {
                lock.lock();
                for (int j = 0; j < 10000; j++) {
                    test.increment();
                }
                lock.unlock();
                latch.countDown();
            });
        }

        latch.await();
        System.out.println("counter = " + test.counter);

        // 拒绝新的线程加入
        service.shutdown();

        // 优雅的关闭service
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                if (!service.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
                    service.shutdownNow();

                    for (int i = 0; i < 10; i++) {
                        if (service.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
                            break;
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }));
    }
}
